"""
文件名: video.py
描述: 视频数据模型定义

本模块包含以下主要功能：
1. Video数据库模型 - SQLAlchemy ORM模型
2. VideoCreate - 视频创建时的数据验证模型
3. VideoUpdate - 视频更新时的数据验证模型
4. VideoInDB - 数据库查询返回的视频模型
5. 视频相关的辅助方法和属性

依赖模块:
   - sqlalchemy: ORM框架和数据库操作
   - pydantic: 数据验证和序列化
   - datetime: 时间处理
   - typing: 类型注解

使用示例:
   >>> from src.models.video import Video, VideoCreate
   >>> video_data = VideoCreate(
   ...     video_id="dQw4w9WgXcQ",
   ...     title="Never Gonna Give You Up",
   ...     channel_id="UCuAXFkgsw1L7xaCfnd5JJOw"
   ... )
   >>> video = Video(**video_data.dict())

注意事项:
   - 视频ID是YouTube提供的唯一标识符
   - 视频信息需要定期同步更新
   - 统计数据可能有延迟
   - 缓存时间不宜过长

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from datetime import datetime, timedelta
from typing import Optional, List, Dict, Any

from sqlalchemy import Column, String, DateTime, Boolean, Text, Integer, BigInteger, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
import uuid

from pydantic import BaseModel, Field, validator

from src.core.database import Base


class Video(Base):
    """
    YouTube视频数据库模型
    
    缓存从YouTube API获取的视频信息
    """
    __tablename__ = "videos"
    
    # 主键和基本信息
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    video_id = Column(String(20), unique=True, index=True, nullable=False, comment="YouTube视频ID")
    channel_id = Column(UUID(as_uuid=True), ForeignKey('channels.id'), nullable=False, index=True, comment="所属频道ID")
    
    # 视频基本信息
    title = Column(String(500), nullable=False, comment="视频标题")
    description = Column(Text, nullable=True, comment="视频描述")
    thumbnail_url = Column(Text, nullable=True, comment="缩略图URL")
    
    # 视频属性
    duration = Column(String(20), nullable=True, comment="视频时长（ISO 8601格式）")
    duration_seconds = Column(Integer, nullable=True, comment="视频时长（秒）")
    category_id = Column(String(10), nullable=True, comment="YouTube分类ID")
    default_language = Column(String(10), nullable=True, comment="默认语言")
    
    # 统计信息
    view_count = Column(BigInteger, default=0, nullable=False, comment="观看次数")
    like_count = Column(BigInteger, default=0, nullable=False, comment="点赞次数")
    comment_count = Column(Integer, default=0, nullable=False, comment="评论次数")
    
    # 发布信息
    published_at = Column(DateTime(timezone=True), nullable=True, comment="发布时间")
    privacy_status = Column(String(20), default="public", nullable=False, comment="隐私状态")
    upload_status = Column(String(20), default="processed", nullable=False, comment="上传状态")
    
    # 视频状态
    is_live = Column(Boolean, default=False, nullable=False, comment="是否为直播")
    is_upcoming = Column(Boolean, default=False, nullable=False, comment="是否为预告")
    is_short = Column(Boolean, default=False, nullable=False, comment="是否为短视频")
    
    # 额外信息（JSON格式）
    tags = Column(JSONB, nullable=True, comment="视频标签")
    thumbnails = Column(JSONB, nullable=True, comment="缩略图信息")
    localized = Column(JSONB, nullable=True, comment="本地化信息")
    
    # 缓存相关
    cached_at = Column(DateTime(timezone=True), nullable=False, server_default=func.now(), comment="缓存时间")
    cache_expires_at = Column(DateTime(timezone=True), nullable=True, comment="缓存过期时间")
    
    # 时间戳
    created_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        nullable=False,
        comment="创建时间"
    )
    updated_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        onupdate=func.now(),
        nullable=False,
        comment="更新时间"
    )
    
    # 关系映射
    # channel = relationship("Channel", back_populates="videos")
    
    def __repr__(self) -> str:
        return f"<Video(id={self.id}, video_id={self.video_id}, title={self.title})>"
    
    @property
    def is_cache_expired(self) -> bool:
        """检查缓存是否过期"""
        if not self.cache_expires_at:
            return True
        return datetime.utcnow() >= self.cache_expires_at
    
    @property
    def is_new(self) -> bool:
        """判断是否为新视频（24小时内发布）"""
        if not self.published_at:
            return False
        return (datetime.utcnow() - self.published_at).total_seconds() < 86400
    
    @property
    def view_count_display(self) -> str:
        """格式化显示观看次数"""
        if self.view_count >= 1_000_000:
            return f"{self.view_count / 1_000_000:.1f}M"
        elif self.view_count >= 1_000:
            return f"{self.view_count / 1_000:.1f}K"
        else:
            return str(self.view_count)
    
    @property
    def duration_display(self) -> str:
        """格式化显示时长"""
        if not self.duration_seconds:
            return "未知"
        
        hours = self.duration_seconds // 3600
        minutes = (self.duration_seconds % 3600) // 60
        seconds = self.duration_seconds % 60
        
        if hours > 0:
            return f"{hours}:{minutes:02d}:{seconds:02d}"
        else:
            return f"{minutes}:{seconds:02d}"
    
    @property
    def published_time_display(self) -> str:
        """格式化显示发布时间"""
        if not self.published_at:
            return "未知"
        
        now = datetime.utcnow()
        delta = now - self.published_at
        
        if delta.days > 0:
            return f"{delta.days}天前"
        elif delta.seconds >= 3600:
            hours = delta.seconds // 3600
            return f"{hours}小时前"
        elif delta.seconds >= 60:
            minutes = delta.seconds // 60
            return f"{minutes}分钟前"
        else:
            return "刚刚"


class VideoBase(BaseModel):
    """视频基础数据模型"""
    video_id: str = Field(..., min_length=1, max_length=20, description="YouTube视频ID")
    title: str = Field(..., min_length=1, max_length=500, description="视频标题")
    description: Optional[str] = Field(None, description="视频描述")
    thumbnail_url: Optional[str] = Field(None, description="缩略图URL")
    duration: Optional[str] = Field(None, max_length=20, description="视频时长")
    duration_seconds: Optional[int] = Field(None, ge=0, description="视频时长（秒）")
    
    class Config:
        from_attributes = True


class VideoCreate(VideoBase):
    """视频创建数据模型"""
    channel_id: uuid.UUID = Field(..., description="所属频道ID")
    category_id: Optional[str] = Field(None, max_length=10, description="YouTube分类ID")
    default_language: Optional[str] = Field(None, max_length=10, description="默认语言")
    view_count: Optional[int] = Field(0, ge=0, description="观看次数")
    like_count: Optional[int] = Field(0, ge=0, description="点赞次数")
    comment_count: Optional[int] = Field(0, ge=0, description="评论次数")
    published_at: Optional[datetime] = Field(None, description="发布时间")
    privacy_status: Optional[str] = Field("public", description="隐私状态")
    upload_status: Optional[str] = Field("processed", description="上传状态")
    is_live: Optional[bool] = Field(False, description="是否为直播")
    is_upcoming: Optional[bool] = Field(False, description="是否为预告")
    tags: Optional[List[str]] = Field(None, description="视频标签")
    thumbnails: Optional[dict] = Field(None, description="缩略图信息")
    cache_expires_at: Optional[datetime] = Field(None, description="缓存过期时间")
    
    @validator("video_id")
    def validate_video_id(cls, v):
        """验证视频ID格式"""
        if not v or len(v) != 11:  # YouTube视频ID长度为11
            raise ValueError("视频ID格式无效")
        return v
    
    @validator("privacy_status")
    def validate_privacy_status(cls, v):
        """验证隐私状态"""
        valid_statuses = ["public", "private", "unlisted"]
        if v and v not in valid_statuses:
            raise ValueError(f"隐私状态必须是: {', '.join(valid_statuses)}")
        return v
    
    @validator("duration_seconds")
    def validate_duration_seconds(cls, v):
        """验证时长"""
        if v is not None and v < 0:
            raise ValueError("视频时长不能为负数")
        return v


class VideoUpdate(BaseModel):
    """视频更新数据模型"""
    title: Optional[str] = Field(None, min_length=1, max_length=500, description="视频标题")
    description: Optional[str] = Field(None, description="视频描述")
    thumbnail_url: Optional[str] = Field(None, description="缩略图URL")
    duration: Optional[str] = Field(None, max_length=20, description="视频时长")
    duration_seconds: Optional[int] = Field(None, ge=0, description="视频时长（秒）")
    category_id: Optional[str] = Field(None, max_length=10, description="YouTube分类ID")
    view_count: Optional[int] = Field(None, ge=0, description="观看次数")
    like_count: Optional[int] = Field(None, ge=0, description="点赞次数")
    comment_count: Optional[int] = Field(None, ge=0, description="评论次数")
    privacy_status: Optional[str] = Field(None, description="隐私状态")
    upload_status: Optional[str] = Field(None, description="上传状态")
    is_live: Optional[bool] = Field(None, description="是否为直播")
    is_upcoming: Optional[bool] = Field(None, description="是否为预告")
    is_short: Optional[bool] = Field(None, description="是否为短视频")
    tags: Optional[List[str]] = Field(None, description="视频标签")
    thumbnails: Optional[dict] = Field(None, description="缩略图信息")
    cached_at: Optional[datetime] = Field(None, description="缓存时间")
    cache_expires_at: Optional[datetime] = Field(None, description="缓存过期时间")
    
    @validator("privacy_status")
    def validate_privacy_status(cls, v):
        """验证隐私状态"""
        if v is not None:
            valid_statuses = ["public", "private", "unlisted"]
            if v not in valid_statuses:
                raise ValueError(f"隐私状态必须是: {', '.join(valid_statuses)}")
        return v
    
    class Config:
        from_attributes = True


class VideoInDB(VideoBase):
    """数据库查询返回的视频模型"""
    id: uuid.UUID = Field(..., description="视频内部ID")
    channel_id: uuid.UUID = Field(..., description="所属频道ID")
    category_id: Optional[str] = Field(None, description="YouTube分类ID")
    view_count: int = Field(..., description="观看次数")
    like_count: int = Field(..., description="点赞次数")
    comment_count: int = Field(..., description="评论次数")
    published_at: Optional[datetime] = Field(None, description="发布时间")
    privacy_status: str = Field(..., description="隐私状态")
    is_live: bool = Field(..., description="是否为直播")
    is_upcoming: bool = Field(..., description="是否为预告")
    is_short: bool = Field(..., description="是否为短视频")
    tags: Optional[List[str]] = Field(None, description="视频标签")
    cached_at: datetime = Field(..., description="缓存时间")
    cache_expires_at: Optional[datetime] = Field(None, description="缓存过期时间")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")
    
    @property
    def is_new(self) -> bool:
        """判断是否为新视频（24小时内发布）"""
        if not self.published_at:
            return False
        return (datetime.utcnow() - self.published_at).total_seconds() < 86400
    
    @property
    def view_count_display(self) -> str:
        """格式化显示观看次数"""
        if self.view_count >= 1_000_000:
            return f"{self.view_count / 1_000_000:.1f}M"
        elif self.view_count >= 1_000:
            return f"{self.view_count / 1_000:.1f}K"
        else:
            return str(self.view_count)
    
    @property
    def duration_display(self) -> str:
        """格式化显示时长"""
        if not self.duration_seconds:
            return "未知"
        
        hours = self.duration_seconds // 3600
        minutes = (self.duration_seconds % 3600) // 60
        seconds = self.duration_seconds % 60
        
        if hours > 0:
            return f"{hours}:{minutes:02d}:{seconds:02d}"
        else:
            return f"{minutes}:{seconds:02d}"


class VideoSummary(BaseModel):
    """视频摘要信息模型（列表页面使用）"""
    id: uuid.UUID = Field(..., description="视频内部ID")
    video_id: str = Field(..., description="YouTube视频ID")
    title: str = Field(..., description="视频标题")
    thumbnail_url: Optional[str] = Field(None, description="缩略图URL")
    duration_seconds: Optional[int] = Field(None, description="视频时长（秒）")
    view_count: int = Field(..., description="观看次数")
    published_at: Optional[datetime] = Field(None, description="发布时间")
    is_live: bool = Field(..., description="是否为直播")
    is_short: bool = Field(..., description="是否为短视频")
    
    @property
    def is_new(self) -> bool:
        """判断是否为新视频（24小时内发布）"""
        if not self.published_at:
            return False
        return (datetime.utcnow() - self.published_at).total_seconds() < 86400
    
    @property
    def view_count_display(self) -> str:
        """格式化显示观看次数"""
        if self.view_count >= 1_000_000:
            return f"{self.view_count / 1_000_000:.1f}M"
        elif self.view_count >= 1_000:
            return f"{self.view_count / 1_000:.1f}K"
        else:
            return str(self.view_count)
    
    @property
    def duration_display(self) -> str:
        """格式化显示时长"""
        if not self.duration_seconds:
            return "未知"
        
        hours = self.duration_seconds // 3600
        minutes = (self.duration_seconds % 3600) // 60
        seconds = self.duration_seconds % 60
        
        if hours > 0:
            return f"{hours}:{minutes:02d}:{seconds:02d}"
        else:
            return f"{minutes}:{seconds:02d}"
    
    class Config:
        from_attributes = True


class VideoStats(BaseModel):
    """视频统计信息模型"""
    total_videos: int = Field(..., description="视频总数")
    total_views: int = Field(..., description="总观看次数")
    total_likes: int = Field(..., description="总点赞次数")
    avg_duration: float = Field(..., description="平均时长（秒）")
    latest_video_at: Optional[datetime] = Field(None, description="最新视频发布时间")
    
    class Config:
        from_attributes = True


class VideoFilter(BaseModel):
    """视频筛选条件模型"""
    search_query: Optional[str] = Field(None, description="搜索关键词")
    channel_ids: Optional[List[uuid.UUID]] = Field(None, description="频道ID列表")
    category_ids: Optional[List[uuid.UUID]] = Field(None, description="分类ID列表")
    published_after: Optional[datetime] = Field(None, description="发布时间过滤（之后）")
    published_before: Optional[datetime] = Field(None, description="发布时间过滤（之前）")
    min_duration: Optional[int] = Field(None, ge=0, description="最小时长（秒）")
    max_duration: Optional[int] = Field(None, ge=0, description="最大时长（秒）")
    min_views: Optional[int] = Field(None, ge=0, description="最小观看次数")
    privacy_status: Optional[str] = Field(None, description="隐私状态")
    is_live: Optional[bool] = Field(None, description="是否为直播")
    is_short: Optional[bool] = Field(None, description="是否为短视频")
    tags: Optional[List[str]] = Field(None, description="标签过滤")
    sort_by: Optional[str] = Field("published_at", description="排序字段")
    sort_order: Optional[str] = Field("desc", description="排序方向")
    
    @validator("sort_by")
    def validate_sort_by(cls, v):
        """验证排序字段"""
        valid_fields = ["published_at", "view_count", "like_count", "duration_seconds", "title"]
        if v and v not in valid_fields:
            raise ValueError(f"排序字段必须是: {', '.join(valid_fields)}")
        return v
    
    @validator("sort_order")
    def validate_sort_order(cls, v):
        """验证排序方向"""
        valid_orders = ["asc", "desc"]
        if v and v not in valid_orders:
            raise ValueError(f"排序方向必须是: {', '.join(valid_orders)}")
        return v